package com.ymttest.database.mongo;

import com.ymt.core.tool.Logger;
import com.ymt.database.MongoDBDriver;
import com.ymttest.business.service.AssertService;
import com.ymttest.utils.EnvSetup;
import com.ymttest.utils.MapUtil;
import com.ymttest.utils.YMTDateUtil;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class YmtMongoDriverFactroy implements MethodInterceptor {
	public static boolean isCheckMgoProdData = false;

	public static boolean IsNewJavaMongoOpen = true;
	public static boolean IsNewMongoOpen = false;
	public static boolean IsOldMongoOpen = false;
	public static boolean IsEsCheck = true;
	public static boolean isOnStage = false;

	public static double waitSec = 3;
	public static int retryTime = 2;

	public static boolean isNewMongoCheck() {
		return isMongoChk(IsNewMongoOpen);
	}

	public static boolean isOldMongoCheck() {
		return isMongoChk(IsOldMongoOpen);
	}

	public static boolean isNewJavaMgoCheck() {
		return isMongoChk(IsNewJavaMongoOpen);
	}

	public static boolean isEsCheck() {
		return isMongoChk(IsEsCheck);
	}

	private static boolean isMongoChk(boolean paramSet) {
		if (paramSet) {
			YMTDateUtil.waitTime(0.5);
			return true;
		} else {
			return false;
		}
	}

	private static MongoDBDriver YmtProductDBdriverNewJava = null;
	private static MongoDBDriver YmtShoppingCartDBdriverNewJava = null;
	private static MongoDBDriver YmtProductDBdriver = null;
	private static MongoDBDriver YmtProductDBdriverNew = null;

	private static MongoDBDriver SellerPromotionDBdrive = null;
	private static MongoDBDriver YmtShoppingCartDBdriverNew = null;
	private static MongoDBDriver ProductHis = null;

	/***
	 * 新java版  mongo服务连接 
	 */
	public static MongoDBDriver getInstance_YmtProductDBdriverNewJava(
			String collectionname) {
		return getInstance(YmtProductDBdriverNewJava, "YmtProducts",
				collectionname, EnvSetup.getSystemUrl("set5_mongoip"), 27017,
				"ymtproducts_user", "123456");
	}

	public static MongoDBDriver getInstance_YmtShoppingCartDBdriverNewJava(
			String collectionname) {
		return getInstance(YmtShoppingCartDBdriverNewJava, "Ymt_ShoppingCart",
				collectionname, EnvSetup.getSystemUrl("set5_mongoip"), 27017,
				"shoppingcartuser", "123456");
	}

	/***
	 * 老Mongo 服务连接
	 * @param collectionname
	 * @return
	 */
	public static MongoDBDriver getInstance_YmtProductDBdriver(
			String collectionname) {
		//for Mongo2.6
		//		return getInstance(YmtProductDBdriver,"YmtProductDB",collectionname,EnvSetup.getSystemUrl("set1_mongoip"));

		//for Mongo3.0
		return getInstance(YmtProductDBdriver, "YmtProductDB", collectionname,
				EnvSetup.getSystemUrl("set5_mongoip"));
	}

	/***
	 * 新Mongo 服务连接
	 * @param collectionname
	 * @return
	 */
	public static MongoDBDriver getInstance_YmtProductDBdriverNew(
			String collectionname) {
		return getInstance(YmtProductDBdriverNew, "YmtBuyerProduct",
				collectionname, EnvSetup.getSystemUrl("set5_mongoip"), 27017,
				"BuyerProductuser", "123456");
	}

	/***
	 * ProductSnapshot 服务连接
	 * @param collectionname
	 * @return
	 */
	public static MongoDBDriver getInstance_ProductSnapshotDBdriverNew(
			String collectionname) {
		return getInstance(YmtProductDBdriverNew, "ProductSnapshot",
				collectionname, EnvSetup.getSystemUrl("set5_mongoip"), 27017,
				"BuyerProductuser", "123456");
	}

	/***
	 * 新Mongo 历史库连接
	 * @param collectionname
	 * @return
	 */
	public static MongoDBDriver getInstance_ProductHis(String collectionname) {
		return getInstance(ProductHis, "ProductHis", collectionname,
				EnvSetup.getSystemUrl("set5_mongoip"), 27017, "producthisuser",
				"123456");
	}

	/***
	 * java Mongo 服务连接
	 * @param collectionname
	 * @return
	 */
	public static MongoDBDriver getInstance_YmtProductsDBdriver(
			String collectionname) {
		return getInstance(YmtProductDBdriverNew, "YmtProducts",
				collectionname, EnvSetup.getSystemUrl("set5_mongoip"), 27017,
				"ymtproducts_user", "123456");
	}

	public static MongoDBDriver getInstance_YmtEvtDatadriver(
			String collectionname) {
		return getInstance(YmtProductDBdriverNew, "Ymt_EvtData",
				collectionname, EnvSetup.getSystemUrl("set5_mongoip"), 27017,
				"Ymt_EvtData_user", "123456");
	}
	/*
	 * 连接满减促销数据库mongo
	 */
	public static MongoDBDriver getInstance_SellerPromotionDBdriverNew(
			String collectionname) {
		return getInstance(SellerPromotionDBdrive, "sellerpromotion",
				collectionname, EnvSetup.getSystemUrl("set5_mongoip"), 27017,
				"sellerpromotionuser", "123456");
	}
	
	/*
	 * 连接费率业务数据库mongo
	 */
	public static MongoDBDriver getInstance_CommissionDBdriverNew(
			String collectionname) {
		return getInstance(SellerPromotionDBdrive, "Commission",
				collectionname, EnvSetup.getSystemUrl("set5_mongoip"), 27017,
				"commissionuser", "123456");
	}
	
	/*
	 * 连接BuyerOrders
	 */
	public static MongoDBDriver getInstance_BuyerOrdersDBdriverNew(
			String collectionname) {
		return getInstance(SellerPromotionDBdrive, "Ymt_BuyerOrders",
				collectionname, EnvSetup.getSystemUrl("set5_mongoip"), 27017,
				"buyerordersuser", "123456");
	}

	private static MongoDBDriver getInstance(MongoDBDriver driver,
			String dbName, String collectionname, String host) {
		return getInstance(driver, dbName, collectionname, host, 27017,
				"productuser", "123456");
	}

	public static MongoDBDriver getInstance_YmtShoppingCartDBdriverNew(
			String collectionname) {
		return getInstance(YmtShoppingCartDBdriverNew, "Ymt_ShoppingCart",
				collectionname, EnvSetup.getSystemUrl("set5_mongoip"), 27017,
				"shoppingcartuser", "123456");
	}

	/***
	 * 获取代理对象
	 */
	private static MongoDBDriver getInstance(MongoDBDriver driver,
			String dbName, String collectionname, String host, int port,
			String userName, String pswd) {
		try {

			Enhancer enhancer = new Enhancer();
			enhancer.setSuperclass(MongoDBDriver.class);
			enhancer.setCallback(new YmtMongoDriverFactroy());

			driver = (MongoDBDriver) enhancer.create(new Class[]{String.class,
					int.class, String.class}, new Object[]{host, port, dbName});
			driver.auth(userName, pswd);

			driver.selectCollection(collectionname);
			return driver;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/***
	 * 代理 尝试重试搜取mongo
	 */
	@Override
	public Object intercept(Object obj, Method method, Object[] args,
			MethodProxy methodProxy) throws Throwable {
		Object result = null;
		//用代理
		if (method.getName().equals("selectPartLimitToMap")) {
			StackTraceElement sElement = Thread.currentThread().getStackTrace()[3];
			Logger.info("代理查询 class:[" + sElement.getFileName() + "],method:["
					+ sElement.getMethodName() + "]");

			for (int i = 0; i < retryTime; i++) {
				Logger.info("代理查询第" + (i + 1) + "次");
				result = methodProxy.invokeSuper(obj, args);

				ArrayList<Map> listRet = (ArrayList<Map>) result;
				if (listRet.size() != 0) {
					return result;
				}

				if (i < retryTime - 1) {
					YMTDateUtil.waitTime((1) * waitSec);
					Logger.comment("wait " + (1) * waitSec + " s");
				}
			}

			ArrayList<Map> listRet = (ArrayList<Map>) result;
			if (listRet.size() == 0) {
				Logger.comment("mongo result is empty. funtion name["
						+ method.getName() + "]");
			}
		} else {
			result = methodProxy.invokeSuper(obj, args);
		}
		return result;

	}

	/***
	 * isUpdate("LiveModel",MapUtil.hashMap("ActivityId", 148186),MapUtil.hashMap("Action", 1))
	 * 等待Mongo修改成功尝试机制
	 * @param collectionname 
	 * @param selectMap
	 * @param isUpdateMap
	 * @return
	 * @throws Exception
	 */
	public static boolean isUpdate(String collectionname,
			Map<String, Object> selectMap, Map<String, Object> isUpdateMap)
			throws Exception {
		MongoDBDriver mdd = YmtMongoDriverFactroy
				.getInstance_YmtProductsDBdriver(collectionname);
		Map<String, Object> ret = new HashMap<String, Object>();

		boolean isAllMatch = true;

		for (int i = 0; i < retryTime; i++) {
			ret = mdd.selectPartLimitToMap(selectMap, 1).get(0);

			isAllMatch = true;

			for (String k : isUpdateMap.keySet()) {
				boolean checkRet = AssertService.assertPreCheck(
						isUpdateMap.get(k), ret.get(k));
				if (!checkRet) {
					isAllMatch = false;
					YMTDateUtil.waitTime(waitSec);
					break;
				}
			}
			if (isAllMatch) {
				return true;
			}
		}
		return isAllMatch;
	}

	public static void main(String[] args) throws Exception {
		isUpdate("LiveModel", MapUtil.hashMap("ActivityId", 148186),
				MapUtil.hashMap("Action", 1));
	}
}
